package net.chathu.airgw.crypto 
{
	import flash.net.Socket;
	import flash.utils.ByteArray;
	import net.chathu.airgw.util.ByteArrayUtil;
	/**
	 * ...
	 * @author ze
	 */
	public class CipherOutputStream 
	{
		private var a:Cipher;
		private var b:Array;
		private var out:Socket;
		
		public function CipherOutputStream(socket:Socket, d1:Cipher)
		{
			//super(outputstream);
			
			a = d1;
			//b = new byte[1024];
			b = new Array();
			for ( var i:int = 0; i < 1024; i++)
			{
				b.push(0);
			}
			out = socket;
		}

				
		public function write(byte:int):void
		{
			
			//byte abyte0[];
			var abyte0:Array = [0];
			//(abyte0 = new byte[1])[0] = (byte)i;
			abyte0[0] = byte & 0xFF;
			a.decryptArray(abyte0);
			////////out.write(abyte0[0]);
			//trace("writing encrpyted byte:" + byte + " encrypted to: " + abyte0[0]);
			out.writeByte(abyte0[0]);
		}

		public function writeBytes(abyte0:Array):void
		{
			//trace("writing " + abyte0.length + " bytes");
			writeBytes2(abyte0, 0, abyte0.length);
		}

		public function writeBytes2(abyte0:Array, i:int, j:int):void
		{
			//boolean flag = false;
			var k:int;
			for(var l:int = 0; l < j; l += k)
			{
				k = j >= 1024 ? 1024 : j;
				a.encrypt(abyte0, i + l, b, 0, k);
				/////out.write(b, 0, k);
				
				var bytearray:ByteArray = new ByteArray();
				for (var c:int = 0; c < b.length; c++)
				{
					bytearray.writeByte(b[c]);
				}
				//trace("encrypted length:" + k);
				out.writeBytes(bytearray, 0, k);
			}

		}
		
		public function writeInt(integer:int):void
		{
			write((integer >> 24 ) & 0xff);
			write((integer >> 16 ) & 0xff);
			write((integer >> 8 ) & 0xff);
			write(integer & 0xff);
		}
		
		/*public function writeUTF(string:String):void {
			trace("writing: " + string);
			var bytearray:ByteArray = new ByteArray();
			bytearray.writeUTFBytes(string);
			bytearray.position = 0;
			var length:int = bytearray.bytesAvailable;
			var array:Array = new Array();
			for (var c:int = 0; c < length; c++) {
				array[c] = bytearray.readByte();
			}
			writeBytes(array);
		}*/
		
		public function writeUTF(str:String):int {
			var strlen:int = str.length;
			var utflen:int = 0;
			var c:int, count:int = 0;

			/* use charAt instead of copying String to char array */
			for (var i:int = 0; i < strlen; i++) {
				//c = str.charAt(i);
				c = str.charCodeAt(i);
				if ((c >= 0x0001) && (c <= 0x007F)) {
					utflen++;
				} else if (c > 0x07FF) {
					utflen += 3;
				} else {
					utflen += 2;
				}
			}

			if (utflen > 65535)
			{
				/*throw new UTFDataFormatException(
					  "encoded string too long: " + utflen + " bytes");*/
				throw new Error("encoded string too long: " + utflen + " bytes");
			}

			//byte[] bytearr = null;
			var bytearr:Array;
			/*if (out instanceof DataOutputStream) {
				  DataOutputStream dos = (DataOutputStream)out;
				  if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
					  dos.bytearr = new byte[(utflen*2) + 2];
				  bytearr = dos.bytearr;
			} else {
				  bytearr = new byte[utflen+2];
			}*/
			bytearr = new Array();
			for (var c2:int = 0; c2 < utflen + 2; c2++)
			{
				bytearr[c2] = 0;
			}
			

			//bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
			bytearr[count++] = ((utflen >>> 8) & 0xFF);
			bytearr[count++] = ((utflen >>> 0) & 0xFF);

			var i2:int=0;
			for (i2=0; i2<strlen; i2++) {
				//c = str.charAt(i);
				c = str.charCodeAt(i2);
				if (!((c >= 0x0001) && (c <= 0x007F))) break;
				//bytearr[count++] = (byte) c;
				bytearr[count++] = c & 0xff;
			 }

			for (;i < strlen; i++){
				//c = str.charAt(i);
				c = str.charCodeAt(i);
				if ((c >= 0x0001) && (c <= 0x007F)) {
					//bytearr[count++] = (byte) c;
					bytearr[count++] = c & 0xff;

				} else if (c > 0x07FF) {
					bytearr[count++] =  (0xE0 | ((c >> 12) & 0x0F));
					bytearr[count++] =  (0x80 | ((c >>  6) & 0x3F));
					bytearr[count++] =  (0x80 | ((c >>  0) & 0x3F));
				} else {
					bytearr[count++] =  (0xC0 | ((c >>  6) & 0x1F));
					bytearr[count++] =  (0x80 | ((c >>  0) & 0x3F));
				}
			}
			
			
			//out.write(bytearr, 0, utflen+2);
			/*var bytearray:ByteArray = new ByteArray();
			for (var cc:int = 0; cc <= bytearr.length; cc++)
			{
				bytearray.writeByte(bytearr[cc]);
			}
			writeBytes2(bytearray, 0, utflen+2);*/
			writeBytes2(bytearr, 0, utflen + 2);
			return utflen + 2;
		}
		
		public function writeNullByteContainingUTF(bytearray:ByteArray):void
		{
			bytearray.position = 0;
			var array:Array = ByteArrayUtil.byteArrayToArray(bytearray);
			write( (array.length >> 8) & 0xFF);
			write( (array.length >> 0) & 0xFF);
			writeBytes(array);
		}
	}

}